/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package data;

/**
 *
 * @author Yang Wang <yang@digitalmenubox.com>
 */
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.ProgressMonitor;

import view.PlayerCanvas;
import view.admin.AdminFrame;
import config.Helper;
import config.Settings;

public class HttpDownloader extends Downloader {

	private String source;
	private String dest;
	private HttpProgressMonitor progressMonitor = null;
	private boolean showProgressWindow = true;

	public boolean isShowProgressWindow() {
		return showProgressWindow;
	}

	@Override
	public void setShowProgressWindow(boolean showProgressWindow) {
		this.showProgressWindow = showProgressWindow;
	}

	public HttpProgressMonitor getProgressMonitor() {
		return progressMonitor;
	}

	public void setProgressMonitor(HttpProgressMonitor progressMonitor) {
		this.progressMonitor = progressMonitor;
	}

	@Override
	public synchronized boolean download(String remoteFile, String downloadedPath, int server) {
		remoteFile = Downloader.getHttpAddress(remoteFile, server);
		this.source = remoteFile;
		this.dest = downloadedPath;
		URL url;
		try {
			url = new URL(source);
			System.out.println("Downloading via http");
			byte[] data = getData(url);
			System.out.println("File downloaded...");
			createFile(this.dest, data);
		} catch (MalformedURLException ex) {
			Logger.getLogger(HttpDownloader.class.getName()).log(Level.SEVERE, null, ex);
		}
		return true;
	}

	private synchronized byte[] getData(URL url) {
		InputStream in = null;
		byte[] data = null;
		HttpDownloadProcessMonitorFrame monitor = null;
		try {
			URLConnection conn = url.openConnection();
			String contentType = conn.getContentType();
			int contentLength = conn.getContentLength();
			// System.out.println("contentLength: " + contentLength);
			if (contentLength < 0) {
				// invalid content length;
				throw new IOException("Invalid content length");
			}
			in = new BufferedInputStream(conn.getInputStream());
			data = new byte[contentLength];
			int bytesRead = 0;
			int offset = 0;
			int acc = 0;
			monitor = new HttpDownloadProcessMonitorFrame("data file", contentLength);
			this.setProgressMonitor(monitor);
			while (offset < contentLength) {
				bytesRead = in.read(data, offset, data.length - offset);
				if (bytesRead == -1) {
					break; // nothing to read
				}
				offset += bytesRead;
				acc += bytesRead;
				if (this.showProgressWindow == true) {
					if (acc > 10 || offset >= contentLength) {
						monitor.bytesTransferred(offset);
						acc = 0;
					}
				}
			}
			in.close();
			if (offset != contentLength) {
				throw new IOException("only read " + offset + " bytes");
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			// clean-up code goes here
			if (in != null) {
				try {
					in.close();
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
			if (monitor != null) {
				monitor.setVisible(false);
				monitor.dispose();
			}
		}
		return data;
	}

	private void createFile(String filename, byte[] data) {
		// System.out.println("Creating " + filename);
		FileOutputStream out = null;
		try {
			if (new File(filename).getParentFile() != null && !new File(filename).getParentFile().exists()) {
				new File(filename).getParentFile().mkdirs();
			}
			out = new FileOutputStream(filename);
			out.write(data);
			out.flush();
			out.close();
		} catch (FileNotFoundException ex) {
			System.err.println("File not found: " + filename);
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			// clean-up code goes here
			if (out != null) {
				try {
					out.close();
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		}
	}

	public static void main(String[] args) {
		HttpDownloader downloader = new HttpDownloader();
		downloader.download("http://www.digitalmarketingbox.com/webtool/boxdata/957/resources.zip", "test.zip", 0);
	}
}

class HttpDownloadProcessMonitor extends ProgressMonitor implements HttpProgressMonitor {

	private int size;
	private static int unitSize = 1024;

	public HttpDownloadProcessMonitor(int size) {
		super(AdminFrame.getInstance(), "Download Progress Monitor", "test", 0, size / unitSize);
		this.size = size / unitSize;
		this.setProgress(0);

	}

	@Override
	public void bytesTransferred(int i) {
		i = i / unitSize;
		this.setProgress(i);
		this.setNote(i + "/" + size + "KBs transfered");
	}
}

class HttpDownloadProcessMonitorFrame extends JFrame implements HttpProgressMonitor, WindowListener {

	private String filename;
	private JProgressBar progressBar;
	private long size;
	private static int unitSize = 1024;

	public HttpDownloadProcessMonitorFrame(String filename, long size) {
		super("Downloading updates");
		this.addWindowListener(this);
		this.setUndecorated(true);
		this.filename = filename;
		progressBar = new JProgressBar(0, (int) (size / unitSize));
		progressBar.setValue(0);
		progressBar.setStringPainted(true);
		progressBar.setPreferredSize(new Dimension(400, 50));
		this.add(progressBar);
		int x = Math.max((Helper.scale(Settings.getPlayerWidth()) - 400) / 2, 0);
		int y = Math.max((Helper.scale(Settings.getPlayerHeight()) - 200), 0);
		this.setBounds(x, y, 400, 50);
		this.pack();
		this.setVisible(true);
		this.setAlwaysOnTop(true);
		PlayerCanvas.getInstance().setAlwaysOnTop(false);
		this.toFront();
	}

	@Override
	public void bytesTransferred(int l) {
		// l = l / unitSize;
		progressBar.setString("Downloading " + filename + ": " + l / unitSize + "KBs/" + progressBar.getMaximum() + "KBs");
		progressBar.setValue(l / unitSize);
		if ((l / unitSize) >= progressBar.getMaximum()) {
			PlayerCanvas.getInstance().setAlwaysOnTop(true);
		}
		// progressBar.(l + "/" + size + "KBs transfered");
	}

	@Override
	public void windowOpened(WindowEvent e) {
		// this.toFront();
	}

	@Override
	public void windowClosing(WindowEvent e) {
	}

	@Override
	public void windowClosed(WindowEvent e) {
	}

	@Override
	public void windowIconified(WindowEvent e) {
		// this.toFront();
	}

	@Override
	public void windowDeiconified(WindowEvent e) {
	}

	@Override
	public void windowActivated(WindowEvent e) {
	}

	@Override
	public void windowDeactivated(WindowEvent e) {
		// this.toFront();
	}
}
